package myBot;

import robocode.*;
import robocode.util.Utils;

import java.io.*;
import java.lang.Math;
import java.util.Random;
import java.awt.*;

import data.MovementData;
import data.RobotData;



public class myBot extends AdvancedRobot {
	
	
	static data.MovementData generationpopulation[]=new data.MovementData[32]; // generation / individ;
	static int generation=0;
	static int individ=0;
	static int fisttime=0;
	
	data.MovementData individual = new data.MovementData();
	double velocity=0;
	double turnrate=0;
	
	public double Evaluator(RobotData Individual,ScannedRobotEvent e){
		double heading=this.getHeading();
		double frontdistance;
		double leftdistance;
		double rightdistance;
		double backdistance;
		double height=this.getBattleFieldHeight();
		double width=this.getBattleFieldWidth();
		double posX=this.getX();
		double posY=this.getY();
		double output=0;
		
		frontdistance=distances.distanceToWall(heading,height,width,posX,posY);
		rightdistance=distances.distanceToWall(heading+Math.PI/2,height,width,posX,posY);
		backdistance=distances.distanceToWall(heading+Math.PI,height,width,posX,posY);
		leftdistance=distances.distanceToWall(heading+Math.PI*(3/4),height,width,posX,posY);
		
		
		output=Individual.velocity*this.getVelocity()/8;
		output+=Individual.bearing*e.getBearingRadians()/Math.PI;
		output+=Individual.distanceToEnemy*distances.intervall(e.getDistance(), 500);
		output+=Individual.headingEnemy*Math.sin(e.getHeading()-heading);
		output+=Individual.robotBackDistanceToWall*distances.intervall(backdistance, 200);
		output+=Individual.robotFrontDistanceToWall*distances.intervall(frontdistance, 200);;
		output+=Individual.robotLeftDistanceToWall*distances.intervall(leftdistance, 200);;
		output+=Individual.robotRightDistanceToWall*distances.intervall(rightdistance, 200);;
		
		output=((1/(1+Math.exp(-output)))*2)-1;
		return output;
	}

	

	
	
	public void run(){
		int bestvalue=0;
		int total=0;
		this.setTurnRadarRightRadians(Double.POSITIVE_INFINITY); 
	    if(individ==generationpopulation.length){
	    	for(int i=0;i<generationpopulation.length;i++){
	    		total+=generationpopulation[i].Fitness;
	    		if(generationpopulation[i].Fitness>bestvalue){
	    			bestvalue=generationpopulation[i].Fitness;
	    		}
	    	}
	    	
	    	out.println("best is: " + bestvalue + "  avg is: " + (total/generationpopulation.length));
	    	data.Breeding.newGeneration(generationpopulation);
	    	individ=0;
	    	generation+=1;
	      }
		if (fisttime==0){
			data.MovementData.generationcreator(generationpopulation);
			fisttime=1;
		}
		this.individual=data.MovementData.getobject(generationpopulation, individ);
		this.setAdjustGunForRobotTurn(true);
	    this.setAdjustRadarForGunTurn(true);
		do {
	            turnRadarRightRadians(Double.POSITIVE_INFINITY); 
	    } while (true);
	    
	}
	public void	onScannedRobot(ScannedRobotEvent e){
		velocity = Evaluator(individual.speedData,e);
		turnrate = Evaluator(individual.turnData,e);

		this.setAhead(velocity*8.5);
		this.setTurnRightRadians((turnrate*10*Math.PI)/150);
		this.setTurnRadarRightRadians(Utils.normalRelativeAngle(getHeadingRadians() + e.getBearingRadians() - getRadarHeadingRadians()) * 1.5);	
	}
	
	public void onDeath(DeathEvent event){
	       this.individual.Fitness=(int) this.getTime();
	       generationpopulation[individ]=this.individual;
	       individ++;
	   }
}
